﻿using Anno.Swagger;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.StaticFiles;
using Newtonsoft.Json.Linq;
using Swashbuckle.AspNetCore.SwaggerUI;

namespace WebApi
{
    public class Startup
    {
        static object LOCK = new object(); 
        Timer timer;
        bool polling = false;
        int pollingInterval = 5000;

        SwaggerUIOptions options;
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddEndpointsApiExplorer();
            services.AddSwaggerGen();

            //services.AddSingleton<SwaggerUIOptions>((provider) =>
            //{
            //    if(options == null) options= new SwaggerUIOptions();
            //    return this.options;
            //});
            //services.AddSingleton<IHostedService, SwaggerUIDocsAggregator>();

        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseDeveloperExceptionPage();

            //// Enable middleware to serve generated Swagger as a JSON endpoint
            //app.UseSwagger(c => { c.RouteTemplate = "{documentName}/swagger.json"; });
            //// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
            //app.UseSwaggerUI(c =>
            //{
            //    //this.options = c;
            //});
            app.UseSwagger();
            app.UseSwaggerUI(it =>
            {
                options = it;
                //it.SwaggerEndpoint("/AnnoSwagger/annoswagger.json", "annoswagger");
                //it.SwaggerEndpoint("/AnnoSwagger/annoswagger2.json", "annoswagger2");
                it.ShowCommonExtensions();
                it.ShowExtensions();

                this.timer = new Timer(async x =>
                {
                    if (this.polling)
                    {
                        return;
                    }
                    lock (LOCK)
                    {
                        this.polling = true;
                    }

                    await this.UpdateDocs();

                    lock (LOCK)
                    {
                        this.polling = false;
                    }

                }, null, 0, pollingInterval);
            });
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.Map("/AppWcf001/docs/swagger.json", () => { return ApiSwagger.SwaggerAnnoJson("http://localhost:5002", "AppWcf001"); });
                endpoints.Map("/App001/docs/swagger.json", () => { return ApiSwagger.SwaggerAnnoJson("http://localhost:5002", "App001"); });
            });
        }

        private async Task UpdateDocs()
        {
            if (options == null) return;
            var urls = new List<UrlDescriptor>();

            //foreach (var kvp in discoveredServices)
            //{
            //    var serviceName = kvp.Key;

            //    if (!urls.Any(u => (u as JObject).GetValue("url").Value<string>().Equals($"/{serviceName}/docs/swagger.json")))
            //    {

            //        urls.Add(JObject.FromObject(new { url = $"/{serviceName}/docs/swagger.json", name = serviceName }));
            //    }
            //}
            var serviceName = "AppWcf001";
            if (!urls.Any(a => a.Name.Equals(serviceName)))
                urls.Add(new UrlDescriptor { Url = $"/{serviceName}/docs/swagger.json", Name = serviceName });

            serviceName = "App001";
            if (!urls.Any(a => a.Name.Equals(serviceName)))
                urls.Add(new UrlDescriptor { Url = $"/{serviceName}/docs/swagger.json", Name = serviceName });

            this.options.ConfigObject.Urls = urls;
        }
    }

    public class SwaggerUIDocsAggregator : IHostedService
    {
        static object LOCK = new object();
        SwaggerUIOptions options;
        Timer timer;
        bool polling = false;
        int pollingInterval = 5000;

        public SwaggerUIDocsAggregator(SwaggerUIOptions _options)
        {
            this.options = _options;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            this.timer = new Timer(async x =>
            {
                if (this.polling)
                {
                    return;
                }

                lock (LOCK)
                {
                    this.polling = true;
                }

                await this.UpdateDocs();

                lock (LOCK)
                {
                    this.polling = false;
                }

            }, null, 0, pollingInterval);
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            this.timer.Dispose();
            this.timer = null;
        }

        private async Task UpdateDocs()
        {
            if (options == null) return;
            var urls = new List<UrlDescriptor>();

            //foreach (var kvp in discoveredServices)
            //{
            //    var serviceName = kvp.Key;

            //    if (!urls.Any(u => (u as JObject).GetValue("url").Value<string>().Equals($"/{serviceName}/docs/swagger.json")))
            //    {

            //        urls.Add(JObject.FromObject(new { url = $"/{serviceName}/docs/swagger.json", name = serviceName }));
            //    }
            //}
            var serviceName = "AppWcf001";
            urls.Add(new UrlDescriptor { Url = $"/{serviceName}/docs/swagger.json", Name = serviceName });

            serviceName = "App001";
            urls.Add(new UrlDescriptor { Url = $"/{serviceName}/docs/swagger.json", Name = serviceName });

            this.options.ConfigObject.Urls = urls;
        }
    }
}
